package platon

import (
	"errors"
	"fmt"
	"platon-tools/go-service/common/constant"
	"platon-tools/go-service/common/util"
	go_logger "platon-tools/go-service/go-logger"
	"platon-tools/go-service/module"
	"platon-tools/go-service/module/model"
)

const (
	LARGER_THAN  string = ">"
	LARGER_EQUAL string = ">="
	LESS_THAN    string = "<"
	LESS_EQUAL   string = "<="

	QUOTA_DISK          string = "disk"
	QUOTA_CPU           string = "cpu"
	QUOTA_MEMORY        string = "memory"
	QUOTA_NETWORK       string = "network"
	QUOTA_IO            string = "io"
	QUOTA_RW            string = "rw"
	QUOTA_RPC_RESP_TIME string = "rpc_resp_time"
)

// 同步数据
func (plt *Platon) SyncMonitor() {
	//var err error
	//
	//r := plt.service.ModuleByName("MYSQLDB")
	//if db, ok := r.(*module.MysqlDB); ok {
	//	var alertRule model.SysAlertRule
	//	where := map[string]interface{}{
	//		"id": ruleId,
	//	}
	//	err = db.Table(model.SysAlertRuleTable).Where(where).First(&alertRule).Error
	//	if err != nil {
	//		go_logger.Logger.Error(err.Error())
	//		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
	//		return
	//	}
	//
	//	alertRule.Status = constant.USER_STATUS_USING
	//	alertRule.UpdateUserName = util.ToString(userName)
	//	alertRule.UpdateTime = time.Now()
	//
	//	err = db.Table(model.SysNodeTable).Save(&alertRule).Error
	//	if err != nil {
	//		go_logger.Logger.Error(err.Error())
	//		return
	//	}
	//
	//	return
	//}
}

// 检查监控项
func (plt *Platon) CheckMonitor() {
	var err error

	r := plt.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {

		var allAlertRules []model.AlertRule
		where := map[string]interface{}{
			"status": constant.NODE_STATUS_USING,
		}
		err = db.Table(model.SysAlertRuleTable).Where(where).Find(&allAlertRules).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			return
		}

		nodeMonitorMap := map[int]model.SysNodeMonitor{}
		for _, alertItem := range allAlertRules {
			monitor, ok := nodeMonitorMap[alertItem.NodePrimaryId]
			if !ok {
				err = db.Table(model.SysAlertRuleTable).Where(map[string]interface{}{"node_primary_id": alertItem.NodePrimaryId}).Find(&monitor).Error
				if err != nil {
					go_logger.Logger.Error("未找到node, " + err.Error())
					continue
				}
				nodeMonitorMap[alertItem.NodePrimaryId] = monitor
			}

			var needAlert bool
			var leftValue interface{}
			switch alertItem.AlertQuota {
			case QUOTA_DISK:
				leftValue = monitor.DiskRatio
			case QUOTA_CPU:
				leftValue = monitor.CPURatio
			case QUOTA_IO:
				leftValue = monitor.IORatio
			case QUOTA_MEMORY:
				leftValue = monitor.MemoryRatio
			case QUOTA_NETWORK:
				leftValue = monitor.NetWorkRatio
			case QUOTA_RW:
				leftValue = monitor.RWAmount
			case QUOTA_RPC_RESP_TIME:
				leftValue = monitor.RPCResponseTime
			default:
				go_logger.Logger.Error(fmt.Sprintf("not suport alert quota: %s", alertItem.AlertQuota))
				continue
			}
			needAlert, err = JudgeAlert(leftValue, alertItem.TriggerValue, alertItem.TriggerOperator)
			if err != nil {
				go_logger.Logger.Error(err.Error())
				continue
			}
			if needAlert {
				// 发通知
			}
		}

		return
	}
}

// 判断是否需要报警
// 左值为当前值，右值为设定值
func JudgeAlert(left, right interface{}, oprator string) (bool, error) {

	if oprator != LARGER_EQUAL && oprator != LARGER_THAN && oprator != LESS_EQUAL && oprator != LESS_THAN {
		return false, errors.New(fmt.Sprintf("Not supported operator: %s", oprator))
	}

	leftLeaf, err := util.ToFloat64(left)
	if err != nil {
		return false, errors.New(fmt.Sprintf("left node convert float fail left: %v", left))
	}

	rightLeaf, err := util.ToFloat64(right)
	if err != nil {
		return false, errors.New(fmt.Sprintf("right node convert float fail left: %v", left))
	}

	if oprator == LARGER_EQUAL {
		return leftLeaf >= rightLeaf, nil
	}

	if oprator == LARGER_THAN {
		return leftLeaf > rightLeaf, nil
	}

	if oprator == LESS_THAN {
		return leftLeaf < rightLeaf, nil
	}

	if oprator == LESS_EQUAL {
		return leftLeaf <= rightLeaf, nil
	}

	return false, nil
}
